package com.gitee.wsl.mathematics.geometry.api.region

import com.gitee.wsl.mathematics.coordinate.Coordinate

interface Region<T:Number,V: Coordinate<T, V>> {

    /** Return true if the region spans the entire space. In other words,
     * a region is full if no points in the space are classified as
     * [outside][RegionLocation.OUTSIDE].
     * @return true if the region spans the entire space
     */
    fun isFull(): Boolean

    /** Return true if the region is completely empty, ie all points in
     * the space are classified as [outside][RegionLocation.OUTSIDE].
     * @return true if the region is empty
     */
    fun isEmpty(): Boolean

    /** Get the centroid, or geometric center, of the region or null if no centroid
     * exists or one exists but is not unique. A centroid will not exist for empty or
     * infinite regions.
     *
     *
     * The centroid of a geometric object is defined as the mean position of
     * all points in the object, including interior points, vertices, and other points
     * lying on the boundary. If a physical object has a uniform density, then its center
     * of mass is the same as its geometric centroid.
     *
     * @return the centroid of the region or null if no unique centroid exists
     * @see [Centroid](https://en.wikipedia.org/wiki/Centroid)
     */
    fun getCentroid(): V

    /** Classify the given point with respect to the region.
     * @param pt the point to classify
     * @return the location of the point with respect to the region
     */
    fun classify(pt: V): RegionLocation?

    /** Return true if the given point is on the inside or boundary
     * of the region.
     * @param pt the point to test
     * @return true if the point is on the inside or boundary of the region
     */
    fun contains(pt: V): Boolean {
        val location = classify(pt)
        return location != null && location != RegionLocation.OUTSIDE
    }

    /** Project a point onto the boundary of the region. Null is returned if
     * the region contains no boundaries (ie, is either [full][.isFull]
     * or [empty][.isEmpty]).
     * @param pt pt to project
     * @return projection of the point on the boundary of the region or null
     * if the region does not contain any boundaries
     */
    //fun project(pt: V): V?

}

